package com.gitee.wsl.compose.draw.sketch

import androidx.compose.animation.core.withInfiniteAnimationFrameMillis
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.IntSize
import com.gitee.wsl.common.ui.draw.DrawCache
import com.gitee.wsl.ext.base.currentTimeMillis
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import timber.log.Timber

/**
 * Run frame time with nanoseconds
 * @param dt - Change it time
 * @param previousTime - previous time to calculate change in time
 */
@Composable
private fun requestAnimationFrame(
    dt: MutableState<Float>,
    previousTime: MutableState<Long>,
) {
    LaunchedEffect(Unit) {
        while (true) {
            withInfiniteAnimationFrameMillis {
                Timber.d("draw infinite ...")
                dt.value = ((it - previousTime.value) / 1E7).toFloat()
                previousTime.value = it
            }
        }
    }
}

/**
 * Simple canvas view to render the sketch
 */

@Composable
internal fun SketchView(
    modifier: Modifier=Modifier,
    stopLoop: Boolean,
    sketch: (drawScope: DrawScope) -> Unit,
) {

    // dt = change in time
    val dt = remember { mutableStateOf(0f) }
    // TODO : Show elapsed time and frames per second on toolbar of window
    var startTime = remember { mutableStateOf(0L) }
    val previousTime = remember { mutableStateOf(currentTimeMillis) }
    val cache = remember { DrawCache() }
    var tinkJob by remember { mutableStateOf<Job?>(null) }
    val size = remember { mutableStateOf(IntSize.Zero) }
    val scope = rememberCoroutineScope()
    val density = LocalDensity.current

    Canvas(modifier = Modifier
        .fillMaxSize()
        .background(Color.Black)
        .onSizeChanged { size.value = it }
        .then(modifier)) {
        val stepFrame = dt.value

        val start = currentTimeMillis
        if (tinkJob == null) {
            tinkJob = scope.launch {
                cache.drawCachedImage(size.value, density) {
                    sketch(this)
                }
            }
        }

        if (tinkJob!!.isCompleted) {
            cache.drawInto(this)
            tinkJob = null
        } else if (cache.isReady) {
            cache.drawInto(this)
        }

        /*val time=K.measureTime {
    cache.drawCachedImage(this.size.toIntSize(), Density(this.density)){
        sketch (this)
    }
    cache.drawInto(this)
}*/

        /* val time=K.measureTime {
    sketch (this)
}*/


        //Timber.d("draw cache time = $time")
        //sketch (this)
        Timber.d("draw intel time = ${currentTimeMillis - start}")

    }


    if (!stopLoop) {
        Timber.d("draw intel animation")
        requestAnimationFrame(dt, previousTime)
    }
}